package cn.bugstack.chatgpt.interfaces;


import cn.bugstack.chatgpt.common.Constants;
import cn.bugstack.chatgpt.domain.chat.ChatCompletionRequest;
import cn.bugstack.chatgpt.domain.chat.ChatCompletionResponse;
import cn.bugstack.chatgpt.domain.chat.Message;
import cn.bugstack.chatgpt.infrastructure.DTO.ChatDTO;
import cn.bugstack.chatgpt.infrastructure.DTO.IdentityDTO;
import cn.bugstack.chatgpt.infrastructure.DTO.IdentityPO;
import cn.bugstack.chatgpt.infrastructure.Mapper.IdentityDAO;
import cn.bugstack.chatgpt.infrastructure.common.Identity;
import cn.bugstack.chatgpt.session.Configuration;
import cn.bugstack.chatgpt.session.OpenAiSession;
import cn.bugstack.chatgpt.session.OpenAiSessionFactory;
import cn.bugstack.chatgpt.session.defaults.DefaultOpenAiSessionFactory;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

/**
 * @author WANG aomizz
 * @description 微信公众号，请求处理服务
 */
@Slf4j
@RestController
@CrossOrigin("*")
@RequestMapping
public class BookController {

    private OpenAiSession openAiSession;

    private Logger logger = LoggerFactory.getLogger(WeiXinPortalController.class);
    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    @Resource
    private IdentityDAO identityDAO;


    public BookController() {
        // 1. 配置文件
        Configuration configuration = new Configuration();
        configuration.setApiHost("https://api.deepseek.com/");
        configuration.setApiKey("sk-8eefbaf4b02840398f3cee8408e8e06d");
        //configuration.setAuthToken("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4ZmciLCJleHAiOjE2ODM0MTgwOTYsImlhdCI6MTY4MzQxNDQ5NiwianRpIjoiODIyM2FhZWQtOWJiNS00NjE0LTljNGYtNjNiMTBkYWE1YjA3IiwidXNlcm5hbWUiOiJ4ZmcifQ.5rsy5bOOJl1UG5e4IzSDU7YbUUZ4d_ZXHz2wbk1ne58");
        // 2. 会话工厂
        OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration);
        // 3. 开启会话
        this.openAiSession = factory.openSession();
        log.info("开始 openAiSession");
    }

    @PostMapping("/api/v1/chat")
    public String chatWithAi(@RequestBody ChatDTO ChatDTO) {
        String userId = ChatDTO.getUserId();
        String message = ChatDTO.getMessage();
        String identityCode = ChatDTO.getIdentityCode();

        //同步处理
        return SynGetresponse(userId, message,identityCode);
    }

    @DeleteMapping("/api/v1/deleteChat")
    public boolean deleteChat(@RequestBody ChatDTO chatDTO){
        String userId = chatDTO.getUserId();
        String identityCode = chatDTO.getIdentityCode();
        log.info("开始清除对话记录,用户：{},模型：{}",userId,identityCode);

        String key = userId + "_" + identityCode;
        log.info("清除缓存key值：{}",key);
        // 方案1的清除
        contextCache.invalidate(key);

        boolean isRemoved = (contextCache.getIfPresent(key) == null); // true 表示移除成功
        if (isRemoved == true){
            log.info("清除对话记录成功,用户：{},模型：{}",userId,identityCode);
            return true;
        }else {
            log.info("清除对话记录失败,用户：{},模型：{}",userId,identityCode);
            return false;
        }

    }

    @GetMapping("/api/v1/getIdentity")
    public List<IdentityPO> getIdentity(){
        log.info("获取所有人物模型...");
        List<IdentityPO> identityPOList = identityDAO.queryBookIdentity();
        log.info("获取所有人物模型...成功！！！");
        return identityPOList;
    }

    @GetMapping("/api/v1/getIdentity/{identityId}")
    public IdentityPO getIdentity(@PathVariable String identityId) {
        log.info("根据identityId获取对应人物模型:{}",identityId);
        IdentityPO identityPO = identityDAO.queryIdentity(identityId);
        log.info("根据identityId获取对应人物模型:{},成功！！！",identityId);
        return identityPO;
    }


    /**
     * 上下文缓存
     */
    private static final int MAX_CONTEXT_LENGTH = 20; // 最大上下文长度
    private Cache<String, CopyOnWriteArrayList<Message>> contextCache = Caffeine.newBuilder()
            .expireAfterWrite(30, TimeUnit.MINUTES) // 设置缓存过期时间为 30 分钟
            .maximumSize(1000) // 设置最大缓存条目数
            .build();

    /**
     * api回答缓存
     */
    private Cache<String, String> tempMessage = Caffeine.newBuilder()
            .expireAfterWrite(30,TimeUnit.SECONDS)
            .maximumSize(5)
            .build();


    private String SynGetresponse(String userId,String message,String identityCode) {
        try {
            log.info("开始接收ai对话请求-userId:{},message:{},identityCode:{}",userId,message,identityCode);

            String text;

            String key = userId + "_" + identityCode;

            // 获取上下文
            CopyOnWriteArrayList<Message> context = contextCache.get(
                    key,
                    k -> new CopyOnWriteArrayList<>()
            );

            // 添加用户消息到上下文
            context.add(Message.builder().role(Constants.Role.USER).content(message).build());

            // 限制上下文长度
            context = trimContext(context);
            //获取gpt回答的内容
            text = SYNdoChatGPTTask(context.toString(),identityCode);


            //异步缓存阻塞主线程 减少响应时间
            String finalText = text;
            CopyOnWriteArrayList<Message> finalContext = context;
            taskExecutor.execute(() -> {
                // 添加 AI 回复到上下文
                finalContext.add(Message.builder().role(Constants.Role.ASSISTANT).content(finalText).build());
                // 更新上下文缓存
                contextCache.put(key, finalContext);
                log.info("上下文已缓存,缓存key：{}",key);
            });


            logger.info("ai对话调用完成-userId:{},text:{}",userId,text);
            return text;
        } catch (Exception e) {
            logger.error("ai对话调用失败,userId:{},identityCode:{}",userId,identityCode);
            return "";
        }
    }

    public String SYNdoChatGPTTask(String content,String identityCode) {
        // OpenAI 请求
        // 1. 创建参数

        List<Message> input = new ArrayList<>();

        // 先添加系统身份消息
        input.add(Message.builder()
                .role(Constants.Role.SYSTEM)
                .content(confirmIdentity(identityCode).getPrompt())
                .build());

        // 再添加用户消息
        input.add(Message.builder()
                .role(Constants.Role.USER)
                .content(content)
                .build());

        ChatCompletionRequest chatCompletion = ChatCompletionRequest.builder()
                .messages(input)
                .model(ChatCompletionRequest.Model.DeepSeek_V3.getCode())
                .build();
        // 2. 发起请求
        ChatCompletionResponse chatCompletionResponse = openAiSession.completions(chatCompletion);
        // 3. 解析结果
        StringBuilder messages = new StringBuilder();
        chatCompletionResponse.getChoices().forEach(e -> {
            messages.append(e.getMessage().getContent());
        });



        return messages.toString();
    }


    /**
     * 限制上下文长度
     * @param context
     * @return
     */
    private CopyOnWriteArrayList<Message> trimContext(CopyOnWriteArrayList<Message> context) {
        if (context.size() <= MAX_CONTEXT_LENGTH) {
            return context;
        }
        // 创建全新的 CopyOnWriteArrayList
        return new CopyOnWriteArrayList<>(
                context.subList(
                        context.size() - MAX_CONTEXT_LENGTH,
                        context.size()
                )
        );
    }

    /**
     * 确定对话身份
     * @param identityCode
     * @return
     */
    private Identity confirmIdentity(String identityCode){
        for (Identity identity : Identity.values()) {
            if (identity.getCode().equals(identityCode)){
                return identity;
            }
        }
        return null;
    }


}
